#include <stdio.h>
#include <stdlib.h>
/* Includes, stl */
#include <utility>
#include <map>
#include <string.h>
#include <iostream>


static char *line = NULL;
static int max_line_len;


static char* readline(FILE *input)
{
	int len;

	if(fgets(line,max_line_len,input) == NULL)
		return NULL;

	while(strrchr(line,'\n') == NULL)
	{
		max_line_len *= 2;
		line = (char *) realloc(line,max_line_len);
		len = (int) strlen(line);
		if(fgets(line+len,max_line_len-len,input) == NULL)
			break;
	}
	return line;
}


int readSvm(const char* filename, float** p_data, float** p_labels, int* p_npoints, int* p_dimension) {
		
	FILE* inputFilePointer = fopen(filename, "r");
	if (inputFilePointer == 0) {
		printf("File not found\n");
		return 0;
	}

	int npoints, dimension,inst_max_index, index;
	float value;
	char *endptr;
	char *idx, *val, *label, *p;

	npoints = 0;
	dimension = 0;
	inst_max_index = 0;
	max_line_len = 1024;
	line = (char*) malloc(max_line_len * sizeof(char));
	
	//determine the number of training samples and the number of features
	while(readline(inputFilePointer)!=NULL)
	{
		p = strtok(line," \t");
		while(1)
		{

			idx = strtok(NULL,":");
			p = strtok(NULL," \t");
						
			inst_max_index = (int) strtol(idx,&endptr,10);

			if(inst_max_index > dimension)
				dimension = inst_max_index;
			

			if(p == NULL || *p == '\n') // check '\n' as ' ' may be after the last feature
				break;
		}
		++npoints;
	}

	rewind(inputFilePointer);
	*(p_npoints) = npoints;
	*(p_dimension) = dimension;

	
	float* data = (float*)malloc(sizeof(float)*npoints*dimension);
	float* labels = (float*)malloc(sizeof(float)*npoints);
	*(p_data) = data;
	*(p_labels) = labels;
	

	for(int i = 0; i < npoints; i++) {

		readline(inputFilePointer);
		label = strtok(line," \t\n");
		labels[i] = atof(label);

		
		while(1)
		{
			idx = strtok(NULL,":");
			val = strtok(NULL," \t");

			if(val == NULL)
				break;

			index = (int) strtol(idx,&endptr,10);
			value = (float) strtod(val,&endptr);

			data[i*dimension + index -1] =value;
		}
	}
	
	fclose(inputFilePointer);
	return 1;
}


